package com.laicunba.service.jzh.impl;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.Date;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.laicunba.constant.FinancingTargetConstant;
import com.laicunba.pojo.BorrowerDO;
import com.laicunba.pojo.FinancingTargetBidDO;
import com.laicunba.pojo.FinancingTargetDO;
import com.laicunba.pojo.JzhAccountDO;
import com.laicunba.pojo.JzhBidOrderDO;
import com.laicunba.pojo.JzhRepaymentDO;
import com.laicunba.service.BorrowerService;
import com.laicunba.service.FinancingTargetBidService;
import com.laicunba.service.FinancingTargetService;
import com.laicunba.service.impl.BaseServiceImpl;
import com.laicunba.service.jzh.JzhAccountService;
import com.laicunba.service.jzh.JzhBidOrderService;
import com.laicunba.service.jzh.JzhRemoteTransferBuService;
import com.laicunba.service.jzh.JzhRepaymentService;
import com.laicunba.util.AssertUtil;
import com.laicunba.util.DateUtil;

@Service
public class JzhRepaymentServiceImpl extends BaseServiceImpl implements JzhRepaymentService {
	private static final MathContext mc = new MathContext(10, RoundingMode.HALF_DOWN);
	@Autowired
	private FinancingTargetBidService financingTargetBidService;
	@Autowired
	private FinancingTargetService financingTargetService;
	@Autowired
	private JzhAccountService jzhAccountService;
	@Autowired
	private JzhBidOrderService jzhBidOrderService;
	@Autowired
	private BorrowerService borrowerService;
	@Autowired
	private JzhRemoteTransferBuService jzhRemoteTransferBuService;

	@Transactional
	@Override
	public Result doRepayment(String bid) {
		// 核对标的数据
		FinancingTargetBidDO bidDO = financingTargetBidService.get(FinancingTargetBidDO.class, bid);
		AssertUtil.assertNotNull(bidDO, "BID_NOT_EXIT");
		AssertUtil.assertTrue(bidDO.getWithdrawPrincipal() == null || bidDO.getWithdrawPrincipal().compareTo(BigDecimal.ZERO) == 0, "WITHDRAW_PRINCIPAL_ERROR");
		AssertUtil.assertTrue(FinancingTargetConstant.TYPE_FIXED.equalsIgnoreCase(bidDO.getType()), "BID_NOT_FIXED");
		AssertUtil.assertTrue(bidDO.isPay(), "BID_NOT_PAY");
		AssertUtil.assertTrue("jzh".equalsIgnoreCase(bidDO.getPayMark()), "NOT_JZH_BID");
		AssertUtil.assertFalse("ACTIVITY".equalsIgnoreCase(bidDO.getPayMark()), "IS_ACTIVITY_BID");
		AssertUtil.assertFalse(bidDO.isTransferCurrent(), "IS_TRANSFER_CURRENT");

		JzhAccountDO jzhAccountDO = jzhAccountService.get(JzhAccountDO.class, bidDO.getBidUserId());
		AssertUtil.assertNotNull(jzhAccountDO, "JZH_ACCOUNT_DO_NOT_EXIST");

		JzhBidOrderDO orderDO = jzhBidOrderService.get(JzhBidOrderDO.class, bidDO.getId());
		AssertUtil.assertNotNull(orderDO, "ORDER_DO_NOT_EXIST");

		FinancingTargetDO financingTargetDO = financingTargetService.get(FinancingTargetDO.class, bidDO.getFinancingTargetId());
		AssertUtil.assertNotNull(financingTargetDO, "FINANCING_TARGET_NOT_EXIST");
		BorrowerDO borrowerDO = borrowerService.get(BorrowerDO.class, financingTargetDO.getBorrowerId());
		AssertUtil.assertNotNull(borrowerDO, "BORROWER_NOT_EXIST");
		// 算息
		bidDO.setWithdrawProfit(countProfit(bidDO, bidDO.getEndProfit()));
		bidDO.setWithdrawPrincipal(bidDO.getBuyAmount());
		BigDecimal yuanAmt = bidDO.getWithdrawPrincipal().add(bidDO.getWithdrawProfit()).setScale(2, BigDecimal.ROUND_HALF_UP);
		int centAmt = yuanAmt.multiply(BigDecimal.valueOf(100)).intValue();

		// 借款人打给投资人
		JzhRemoteTransferBuService.Param param = new JzhRemoteTransferBuService.Param();
		param.setInCustNo(orderDO.getOutCustNo());
		param.setOutCustNo(orderDO.getInCustNo());
		param.setMchntTxnSsn(orderDO.getMchntTxnSsn() + "B");
		param.setCentAmt(centAmt);
		param.setRem("定期回款");
		param.setContractNo("");
		JzhRemoteTransferBuService.Result transferResult = jzhRemoteTransferBuService.post(param);
		AssertUtil.assertNotNull(transferResult, "JZH_RESULT_NULL");
		AssertUtil.assertTrue("0000".equals(transferResult.getRespCode()), transferResult.getRespCode() + ":" + transferResult.getRespDesc());

		AssertUtil.assertTrue(financingTargetBidService.updateSkipCheckOwner(bidDO), "UPDATE_BID_ERROR");
		// 加本地余额
		BigDecimal balance = jzhAccountService.add(jzhAccountDO.getId(), yuanAmt, param.getMchntTxnSsn(), "BID_REPAYMENT", "bid:" + bidDO.getId());

		// 本地打款记录
		JzhRepaymentDO jzhRepaymentDO = new JzhRepaymentDO();
		jzhRepaymentDO.setBid(bidDO.getId());
		jzhRepaymentDO.setBorrowerId(borrowerDO.getId());
		jzhRepaymentDO.setCentAmt(centAmt);
		jzhRepaymentDO.setYuanAmt(yuanAmt);
		jzhRepaymentDO.setContractNo(orderDO.getContractNo());
		jzhRepaymentDO.setInCustNo(param.getInCustNo());
		jzhRepaymentDO.setOutCustNo(param.getOutCustNo());
		jzhRepaymentDO.setUserId(bidDO.getBidUserId());
		jzhRepaymentDO.setMchntTxnSsn(param.getMchntTxnSsn());
		jzhRepaymentDO.setRem(param.getRem());
		jzhRepaymentDO.setType("D_BID");
		this.create(jzhRepaymentDO);

		Result result = new Result();
		result.setPrinciple(bidDO.getWithdrawPrincipal());
		result.setProfit(bidDO.getWithdrawProfit());
		return result;
	}

	/**
	 * 计算剩余收益<br>
	 * 公式: 剩余本金 * (年化/36500)* (开始计息到当前时间的天数) - 应扣息
	 * 
	 * @param bidDO
	 * @return
	 */

	private BigDecimal countProfit(FinancingTargetBidDO bidDO, Date date) {
		if (date == null) {
			return BigDecimal.ZERO;
		}
		if (bidDO.getWithdrawPrincipal() == null) {
			bidDO.setWithdrawPrincipal(BigDecimal.ZERO);
		}
		if (bidDO.getDeductionProfit() == null) {
			bidDO.setDeductionProfit(BigDecimal.ZERO);
		}
		if (bidDO.getBeginProfit() == null) {
			return BigDecimal.ZERO;
		}

		int days = DateUtil.days(bidDO.getReBeginProfit() != null ? bidDO.getReBeginProfit() : bidDO.getBeginProfit(), date);
		if (days == 0) {
			return BigDecimal.ZERO;
		}
		BigDecimal profit = bidDO.getBuyAmount();// .subtract(bidDO.getWithdrawPrincipal());
		if (bidDO.getWithdrawPrincipal() != null) {
			profit = profit.subtract(bidDO.getWithdrawPrincipal());
		}
		profit = profit.multiply(bidDO.getAnnualizedRates().divide(BigDecimal.valueOf(36500), mc));
		profit = profit.multiply(BigDecimal.valueOf(days));
		profit = profit.add(bidDO.getExpireSendProfit()!=null?bidDO.getExpireSendProfit():BigDecimal.ZERO);
		return profit;
	}

}
